#!/usr/bin/env python3
"""
Markdown to LaTeX converter for Claude Code Development Book
Handles proper escaping, code blocks, tables, and formatting
"""

import re
import os
from pathlib import Path

def escape_latex_special_chars(text):
    """Escape special LaTeX characters in regular text"""
    # Dictionary of LaTeX special characters and their escapes
    # Handle backslash first, then others
    
    # First handle backslashes specially - but not if they're already LaTeX commands
    if not text.strip().startswith('\\') and '\\' in text:
        # Replace standalone backslashes with textbackslash, but preserve LaTeX commands
        # This is a bit complex - we need to handle paths like \wsl.localhost\Ubuntu
        import re
        # Replace backslashes that are not followed by LaTeX command characters
        text = re.sub(r'\\(?![a-zA-Z{])', r'\\textbackslash{}', text)
    
    latex_chars = {
        '{': r'\{',
        '}': r'\}', 
        '$': r'\$',
        '&': r'\&',
        '%': r'\%',
        '#': r'\#',
        '^': r'\textasciicircum{}',
        '_': r'\_',
        '~': r'\textasciitilde{}',
    }
    
    # Only escape if not in code block or math mode
    for char, escape in latex_chars.items():
        text = text.replace(char, escape)
    return text

def convert_headers(text):
    """Convert markdown headers to LaTeX sections"""
    # Convert headers (# ## ### ####)
    text = re.sub(r'^# (.*?)$', r'\\chapter{\1}', text, flags=re.MULTILINE)
    text = re.sub(r'^## (.*?)$', r'\\section{\1}', text, flags=re.MULTILINE)
    text = re.sub(r'^### (.*?)$', r'\\subsection{\1}', text, flags=re.MULTILINE)
    text = re.sub(r'^#### (.*?)$', r'\\subsubsection{\1}', text, flags=re.MULTILINE)
    text = re.sub(r'^##### (.*?)$', r'\\paragraph{\1}', text, flags=re.MULTILINE)
    
    return text

def convert_emphasis(text):
    """Convert markdown emphasis to LaTeX"""
    # Bold text **text** or __text__
    text = re.sub(r'\*\*(.*?)\*\*', r'\\textbf{\1}', text)
    text = re.sub(r'__(.*?)__', r'\\textbf{\1}', text)
    
    # Italic text *text* or _text_
    text = re.sub(r'(?<!\*)\*([^\*]+?)\*(?!\*)', r'\\textit{\1}', text)
    text = re.sub(r'(?<!_)_([^_]+?)_(?!_)', r'\\textit{\1}', text)
    
    return text

def convert_lists(text):
    """Convert markdown lists to LaTeX"""
    lines = text.split('\n')
    in_list = False
    list_type = None
    result = []
    
    for line in lines:
        # Unordered list
        if re.match(r'^[\s]*[-\*\+]\s+', line):
            if not in_list or list_type != 'itemize':
                if in_list:
                    result.append(f'\\end{{{list_type}}}')
                result.append('\\begin{itemize}')
                in_list = True
                list_type = 'itemize'
            
            content = re.sub(r'^[\s]*[-\*\+]\s+', '', line)
            result.append(f'\\item {content}')
        
        # Ordered list
        elif re.match(r'^[\s]*\d+\.\s+', line):
            if not in_list or list_type != 'enumerate':
                if in_list:
                    result.append(f'\\end{{{list_type}}}')
                result.append('\\begin{enumerate}')
                in_list = True
                list_type = 'enumerate'
            
            content = re.sub(r'^[\s]*\d+\.\s+', '', line)
            result.append(f'\\item {content}')
        
        else:
            if in_list and line.strip() == '':
                result.append(f'\\end{{{list_type}}}')
                in_list = False
                list_type = None
            result.append(line)
    
    if in_list:
        result.append(f'\\end{{{list_type}}}')
    
    return '\n'.join(result)

def convert_code_blocks(text):
    """Convert markdown code blocks to LaTeX listings blocks"""
    # Handle fenced code blocks with language specification
    def replace_code_block(match):
        language = match.group(1) if match.group(1) else 'text'
        code_content = match.group(2)
        
        # Map common languages to listings-supported ones
        lang_map = {
            'bash': 'bash',
            'shell': 'bash', 
            'python': 'Python',
            'py': 'Python',
            'javascript': 'Java',  # listings doesn't have JS, use Java as closest
            'js': 'Java',
            'json': 'bash',  # Use bash for JSON (better than nothing)
            'yaml': 'bash',
            'yml': 'bash', 
            'markdown': 'bash',
            'md': 'bash',
            'latex': 'TeX',
            'tex': 'TeX', 
            'sql': 'SQL',
            'html': 'HTML',
            'css': 'HTML',
            'xml': 'XML',
            'dockerfile': 'bash',
            'makefile': 'make',
            'c': 'C',
            'cpp': 'C++',
            'java': 'Java'
        }
        
        mapped_lang = lang_map.get(language.lower(), '')
        
        if mapped_lang:
            return f'\\begin{{lstlisting}}[language={mapped_lang}]\n{code_content}\n\\end{{lstlisting}}'
        else:
            return f'\\begin{{lstlisting}}\n{code_content}\n\\end{{lstlisting}}'
    
    # Match fenced code blocks
    text = re.sub(r'^```(\w*)\n(.*?)^```', replace_code_block, text, flags=re.MULTILINE | re.DOTALL)
    
    # Handle inline code `code`
    text = re.sub(r'`([^`]+)`', r'\\texttt{\1}', text)
    
    return text

def convert_tables(text):
    """Convert markdown tables to LaTeX tables"""
    lines = text.split('\n')
    result = []
    in_table = False
    
    i = 0
    while i < len(lines):
        line = lines[i]
        
        # Check if this line looks like a table row
        if '|' in line and not in_table:
            # Look ahead to see if next line is a separator
            if i + 1 < len(lines) and re.match(r'^\s*\|?[\s\-\|:]+\|?\s*$', lines[i + 1]):
                # Start table
                in_table = True
                
                # Parse header row
                headers = [cell.strip() for cell in line.split('|') if cell.strip()]
                num_cols = len(headers)
                
                result.append('\\begin{table}[H]')
                result.append('\\centering')
                result.append(f'\\begin{{tabular}}{{{"|".join(["l"] * num_cols)}}}')
                result.append('\\hline')
                result.append(' & '.join(headers) + ' \\\\')
                result.append('\\hline')
                
                i += 2  # Skip header and separator line
                continue
        
        elif '|' in line and in_table:
            # Table row
            cells = [cell.strip() for cell in line.split('|') if cell.strip()]
            if cells:
                result.append(' & '.join(cells) + ' \\\\')
        
        elif in_table and not ('|' in line):
            # End of table
            result.append('\\hline')
            result.append('\\end{tabular}')
            result.append('\\end{table}')
            in_table = False
            result.append(line)
        
        else:
            result.append(line)
        
        i += 1
    
    if in_table:
        result.append('\\hline')
        result.append('\\end{tabular}')
        result.append('\\end{table}')
    
    return '\n'.join(result)

def convert_links(text):
    """Convert markdown links to LaTeX"""
    # [text](url) -> \href{url}{text}
    text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'\\href{\2}{\1}', text)
    return text

def convert_markdown_to_latex(md_content):
    """Main conversion function"""
    # Start with the content
    latex_content = md_content
    
    # Convert code blocks first (before escaping special chars)
    latex_content = convert_code_blocks(latex_content)
    
    # Convert tables
    latex_content = convert_tables(latex_content)
    
    # Convert headers BEFORE escaping special characters
    latex_content = convert_headers(latex_content)
    latex_content = convert_emphasis(latex_content)
    latex_content = convert_lists(latex_content)
    latex_content = convert_links(latex_content)
    
    # Process line by line to handle escaping properly
    lines = latex_content.split('\n')
    processed_lines = []
    in_code_block = False
    
    for line in lines:
        # Check if we're entering/leaving a code block
        if line.strip().startswith('\\begin{lstlisting}'):
            in_code_block = True
            processed_lines.append(line)
            continue
        elif line.strip().startswith('\\end{lstlisting}'):
            in_code_block = False
            processed_lines.append(line)
            continue
        
        # Don't escape content inside code blocks or LaTeX commands
        if not in_code_block and not line.strip().startswith('\\'):
            line = escape_latex_special_chars(line)
        
        processed_lines.append(line)
    
    latex_content = '\n'.join(processed_lines)
    
    return latex_content

def process_file(md_file, output_dir):
    """Process a single markdown file"""
    print(f"Processing {md_file}")
    
    # Read markdown file
    with open(md_file, 'r', encoding='utf-8') as f:
        md_content = f.read()
    
    # Convert to LaTeX
    latex_content = convert_markdown_to_latex(md_content)
    
    # Generate output filename
    basename = Path(md_file).stem
    if basename.startswith('appendix-'):
        output_filename = f"{basename}.tex"
    else:
        # Extract chapter number if present
        match = re.match(r'(\d+)-(.*)', basename)
        if match:
            chapter_num = match.group(1)
            chapter_name = match.group(2)
            output_filename = f"{chapter_num}-{chapter_name}.tex"
        else:
            output_filename = f"{basename}.tex"
    
    # Write LaTeX file
    output_path = Path(output_dir) / output_filename
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(latex_content)
    
    print(f"Created {output_path}")
    return output_path

def main():
    """Main function to convert all markdown files"""
    book_dir = Path("/home/linden/claude/packages/ccwork/claude-code-development-book")
    chapters_dir = book_dir / "chapters"
    
    # Create chapters directory if it doesn't exist
    chapters_dir.mkdir(exist_ok=True)
    
    # Find all markdown files
    md_files = []
    
    # Foundation files
    foundation_dir = book_dir / "part-i-foundation"
    md_files.extend(sorted(foundation_dir.glob("*.md")))
    
    # Task types files
    task_types_dir = book_dir / "part-ii-task-types"
    md_files.extend(sorted(task_types_dir.glob("*.md")))
    
    # Advanced files
    advanced_dir = book_dir / "part-iii-advanced"
    md_files.extend(sorted(advanced_dir.glob("*.md")))
    
    # Appendices files
    appendices_dir = book_dir / "appendices"
    md_files.extend(sorted(appendices_dir.glob("*.md")))
    
    print(f"Found {len(md_files)} markdown files to convert")
    
    # Process each file
    for md_file in md_files:
        try:
            process_file(md_file, chapters_dir)
        except Exception as e:
            print(f"Error processing {md_file}: {e}")
    
    print("Conversion complete!")

if __name__ == "__main__":
    main()